package com.woniuxy.ann;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO:
 * <P> Date: 2022/4/21:16:36
 * <P> Description:
 */

public class MyAnnTest {

    static final HashMap<Integer, Dict> dicts;

    static {
        dicts = new HashMap<>();
        dicts.put(2, new Dict(2L, 1L, "区域", 1L, "REGION"));
        dicts.put(3, new Dict(3L, 2L, "华南区域", 1L, "HUA_NAN_REGION"));
        dicts.put(4, new Dict(4L, 2L, "东北区域", 2L, "DONG_BEI_REGION"));
        dicts.put(5, new Dict(5L, 2L, "西南区域", 3L, "XI_NAN_REGION"));

        dicts.put(1, new Dict(6L, 2L, "成色", 0L, "CONDITION"));
        dicts.put(6, new Dict(7L, 6L, "万足金1000", 1L, ""));
        dicts.put(7, new Dict(8L, 6L, "千足金9999", 2L, ""));

        dicts.put(8, new Dict(8L, 3L, "A仓库", 1L, ""));
        dicts.put(9, new Dict(9L, 3L, "B仓库", 2L, ""));
        dicts.put(10, new Dict(10L, 3L, "C仓库", 3L, ""));

        dicts.put(11, new Dict(11L, 4L, "A仓库", 1L, ""));
        dicts.put(12, new Dict(12L, 4L, "B仓库", 2L, ""));
        dicts.put(13, new Dict(13L, 4L, "C仓库", 3L, ""));


    }

    public static void main(String[] args) throws Exception {

        Test test = new Test("2", "2", "3");
        setDict(test,test.clone());

    }


    public static <T> void setDict(T target) throws Exception {

        Class<?> tClass = target.getClass();

        Object targetClone = tClass.newInstance();





        Field[] declaredFields = tClass.getDeclaredFields();

        try {
            getMyField(declaredFields, target, (T) targetClone);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }


    public static <T> void setDict(T target,T targetClone) throws Exception {

        Class<?> tClass = target.getClass();






        Field[] declaredFields = tClass.getDeclaredFields();

        try {
            getMyField(declaredFields, target, targetClone);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    /**
     * <P>Author ideaAdmin
     * <P>TODO: 设置当前对象的所有属性
     * <P>Date 22:15 2022/4/21
     * <P>* @param declaredFields
    * @param target
    * @param targetClone
     * <P>* @return java.lang.reflect.Field
     **/
    protected static <T> Field getMyField(Field[] declaredFields, T target, T targetClone) throws Exception {
        for (Field declaredField : declaredFields) {

            //TODO 如果拥有注解
            //获得我想要的注解
            if (isHaveAnnotations(declaredField) != null) {
                Map<String, Annotation> annotations = getAnnotations(declaredField);
                //TODO 获得数组对象 然后获得缓存的数据 遍历缓存 然后设置值

                //TODO 获得dict的当前子类 获得它的注解值
                MyDictCode myDictCode = (MyDictCode) annotations.get("dict");
                setValue(myDictCode, declaredField, target, targetClone);

            }

        }
        System.out.println(targetClone);
        return null;
    }

    protected static <T> void setValue(Annotation myDictAnno, Field field, T target, T targetClone) throws NoSuchFieldException, IllegalAccessException {
        List<Dict> collect = dicts.entrySet()
                .stream()
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        AtomicReference<MyDictCode> myDictCodeAtomicReference = new AtomicReference<>();
        if (myDictAnno instanceof MyDictCode) {
            myDictCodeAtomicReference.set((MyDictCode) myDictAnno);
        }

        if (myDictCodeAtomicReference.get() == null) {
            return;
        }
        //TODO  如果当前有直接父级菜单
        if (!myDictCodeAtomicReference.get().isSon()) {
            ifNoSon(field, targetClone, collect, myDictCodeAtomicReference);
            return;
        }


        // TODO 否则获取属性值去查询
        String value = myDictCodeAtomicReference.get().value();
        // 获得父类菜单的属性
        Field declaredField = target.getClass().getDeclaredField(value);
        declaredField.setAccessible(true);

        // 获得父类菜单的注解
        Map<String, Annotation> annotations = getAnnotations(declaredField);
        myDictCodeAtomicReference.set((MyDictCode) annotations.get("dict"));
        Dict fartherDict = ifNoSon(declaredField, target, collect, myDictCodeAtomicReference);

        if (fartherDict == null) {
            throw new RuntimeException("当前附加菜单为空");
        }
        // Object o = declaredField.get(target);

        // 获得父级菜单的id 通过dictcode和value查询
        // 查找当前父级菜单下面的所有的list
        List<Dict> collect1 = collect.stream().filter(dict -> {
            return dict.getParentId().compareTo(fartherDict.getId()) == 0;
        }).collect(Collectors.toList());

        setTargetClone(field, target, targetClone, collect1);


    }


    /**
     * <P>Author ideaAdmin
     * <P>TODO: 如果当前就是二级菜单 调用这个方法
     * <P>Date 22:12 2022/4/2 1
     * <P>* @param field
     *
     * @param targetClone
     * @param collect
     * @param myDictCodeAtomicReference <P>* @return com.woniuxy.ann.Dict
     **/
    protected static <T> Dict ifNoSon(Field field, T targetClone, List<Dict> collect,
                                    AtomicReference<MyDictCode> myDictCodeAtomicReference) {
        // 获得对应的字典列表的父级菜单字典
        Optional<Dict> first = collect.stream().filter(dict -> {

            return dict.getDictCode().equals(myDictCodeAtomicReference.get().value());

        }).findFirst();


        AtomicReference<Dict> myDict = new AtomicReference<>();

        first.ifPresent(myDict::set);

        List<Dict> collect1 = null;

        if (myDict.get() == null) {
            return null;
        }
        //TODO 获得对应的字典List 集合
        collect1 = collect.stream().filter(dict -> {
                    return dict.getParentId().compareTo(myDict.get().getId()) == 0;
                })
                .collect(Collectors.toList());


        return setTargetClone(field, targetClone, targetClone, collect1);
    }



    /**
     * <P>Author ideaAdmin
     * <P>TODO: 根据target的设置其对应的属性值
     * <P>Date 22:10 2022/4/21
     * <P>* @param field
     *
     * @param target
     * @param targetClone
     * @param collect1    <P>* @return com.woniuxy.ann.Dict
     **/
    protected static <T> Dict setTargetClone(Field field, T target, T targetClone, List<Dict> collect1) {
        field.setAccessible(true);


        // 获得对应的字典
        Optional<Dict> optionalDict = collect1.stream()
                .filter(dict -> {
                    try {
                        return dict.getValue().compareTo(Long.valueOf(field.get(target).toString())) == 0;
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    return false;
                }).
                findFirst();
        optionalDict.ifPresent(dict -> {
            try {
                field.set(targetClone, dict.getName());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });

        // 写入到对应的字段
        AtomicReference<Dict> source = new AtomicReference<>();
        optionalDict.ifPresent(dict -> {
            try {
                source.set(dict);
                field.set(targetClone, dict.getName());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        return source.get() == null ? null : source.get();
    }

    /**
     * <P>Author ideaAdmin
     * <P>TODO: 是否拥有自定义注解
     * <P>Date 22:14 2022/4/21
     * <P>* @param declaredField
     * <P>* @return java.lang.reflect.Field
     **/
    protected static Field isHaveAnnotations(Field declaredField) {
        Annotation[] annotations = declaredField.getAnnotations();
        if (annotations.length > 0 &&
                isHaveMyDict(declaredField) &&
                isHaveMyExcel(declaredField)
        ) {
            return declaredField;
        }
        return null;
    }

    /**
     * TODO: 是否拥有 MyDict 注解 和 MyExcel 注解
     **/
    protected static boolean isHaveMyDict(Field declaredField) {
        Annotation[] annotations = declaredField.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof MyDictCode) {
                return true;
            }
        }
        return false;
    }

    /**
     * <P>Author ideaAdmin
     * <P>TODO: 是否有MyExcel注解
     * <P>Date 22:14 2022/4/21
     * <P>* @param declaredField
     * <P>* @return boolean
     **/
    protected static boolean isHaveMyExcel(Field declaredField) {
        Annotation[] annotations = declaredField.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof MyExcel) {
                return true;
            }
        }
        return false;
    }

    /**
     * <P>Author ideaAdmin
     * <P>TODO: 是否有myDict注解
     * <P>Date 22:15 2022/4/21
     * <P>* @param declaredField
     * <P>* @return java.util.Map<java.lang.String,java.lang.annotation.Annotation>
     **/
    protected static Map<String, Annotation> getAnnotations(Field declaredField) {
        Annotation[] annotations = declaredField.getAnnotations();
        Map<String, Annotation> myAnno = new HashMap();

        for (Annotation annotation : annotations) {
            if (annotation instanceof MyDictCode) {
                myAnno.put("dict", annotation);
            }
            if (annotation instanceof MyExcel) {
                myAnno.put("excel", annotation);
            }
        }
        return myAnno;

    }
}
